home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Dev / GNU-SMALLTALK.lha / mstsym.c < prev    next >
C/C++ Source or Header  |  1992-02-15  |  22KB  |  879 lines

  1. /***********************************************************************
  2.  *
  3.  *    Symbol Table module.
  4.  *
  5.  ***********************************************************************/
  6.  
  7. /***********************************************************************
  8.  *
  9.  * Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
  10.  * Written by Steve Byrne.
  11.  *
  12.  * This file is part of GNU Smalltalk.
  13.  *
  14.  * GNU Smalltalk is free software; you can redistribute it and/or modify it
  15.  * under the terms of the GNU General Public License as published by the Free
  16.  * Software Foundation; either version 1, or (at your option) any later 
  17.  * version.
  18.  * 
  19.  * GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
  20.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
  21.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  22.  * more details.
  23.  * 
  24.  * You should have received a copy of the GNU General Public License along with
  25.  * GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
  26.  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  
  27.  *
  28.  ***********************************************************************/
  29.  
  30.  
  31. /*
  32.  *    Change Log
  33.  * ============================================================================
  34.  * Author      Date       Change 
  35.  * sbyrne    16 May 90      Changed usages of "entry" to "ent" to prevent
  36.  *              collisions with C compilers which have this
  37.  *              identifier as a reserved word.
  38.  *
  39.  * sbyrne    21 Apr 90      Addded byteArraySymbol.
  40.  *
  41.  * sbyrne    13 Jan 90      Added thisContextSymbol.
  42.  *
  43.  * sbyrne    19 Dec 89      Rebuilt symbol table.  Used to use the main OOP table
  44.  *              as a symbol table, due to issues involving initial
  45.  *              bootstrapping of the system.  Now using open hash
  46.  *              table built of arrays and linked lists, so that no
  47.  *              special precautions need be taken by the GC system or
  48.  *              the image save/restore facility.
  49.  *
  50.  * sbyrne    25 Jul 89      Changed undeclareName to take a parameter that
  51.  *              controls whether the frame index is decremented or
  52.  *              not.  It appears that each block gets its own,
  53.  *              non-shared temporaries/arguments, so that if the
  54.  *              block is used in a process, other blocks won't have
  55.  *              strange things happening to their arguments.
  56.  *
  57.  * sbyrne     5 Jan 89      Created.
  58.  *
  59.  */
  60.  
  61. #include "mst.h"
  62. #include "mstsym.h"
  63. #include "mstoop.h"
  64. #include "mstcomp.h"
  65. #include "mstdict.h"
  66. #include "msttree.h"
  67. #include <stdio.h>
  68. #include <ctype.h>
  69. #ifdef HAS_ALLOCA_H
  70. #include <alloca.h>
  71. #endif
  72.  
  73. /* if defined, use the hash algorithm given in the dragon book (see usage for
  74.    better reference. */
  75. #define dragon_book
  76.  
  77. #define    max(x, y) \
  78.   ( ((x) > (y)) ? (x) : (y) )
  79.  
  80. #define isSymbol(oop) \
  81.    ( !isNil(oop) && (oopClass(oop) ==  symbolClass) )
  82.  
  83. typedef struct {
  84.   OBJ_HEADER;
  85.   OOP        nextLink;
  86.   OOP        symbol;
  87. } *SymLink;
  88.  
  89. OOP            andColonSymbol, atColonPutColonSymbol, atColonSymbol,
  90.             atEndSymbol, bitAndColonSymbol, bitOrColonSymbol,
  91.             bitShiftColonSymbol, blockCopyColonSymbol, classSymbol,
  92.             divideSymbol, doColonSymbol, equalSymbol,
  93.             greaterEqualSymbol, greaterThanSymbol,
  94.             ifFalseColonIfTrueColonSymbol, ifFalseColonSymbol,
  95.             ifTrueColonIfFalseColonSymbol, ifTrueColonSymbol,
  96.             integerDivideSymbol, lessEqualSymbol, lessThanSymbol,
  97.             minusSymbol, newColonSymbol, newSymbol,
  98.             nextPutColonSymbol, nextSymbol, notEqualSymbol,
  99.             notSameObjectSymbol, orColonSymbol, plusSymbol,
  100.             remainderSymbol, sameObjectSymbol, sizeSymbol,
  101.             thisContextSymbol,
  102.             timesSymbol, valueColonSymbol,
  103.             valueColonValueColonSymbol,
  104.             valueColonValueColonValueColonSymbol,
  105.              valueWithArgumentsColonSymbol,
  106.             valueSymbol,
  107.             whileFalseColonSymbol, whileTrueColonSymbol, orSymbol,
  108.             andSymbol, superSymbol, nilSymbol, trueSymbol,
  109.             falseSymbol, selfSymbol,
  110.             doesNotUnderstandColonSymbol, unknownSymbol,
  111.             charSymbol, stringSymbol, stringOutSymbol, 
  112.             symbolSymbol, intSymbol, longSymbol, doubleSymbol,
  113.             voidSymbol, variadicSymbol, cObjectSymbol, 
  114.             smalltalkSymbol, symbolTable, byteArraySymbol,
  115.               byteArrayOutSymbol;
  116.  
  117. #ifdef symbol_table_profiling
  118. int            adds = 0, reused = 0, reprobes = 0,
  119.             hitsOn[OOP_TABLE_SIZE];
  120. #endif /* symbol_table_profiling */
  121.  
  122. void             printString();
  123.  
  124. static SymbolEntry    allocSymbolEntry();
  125. static Symbol        makeNewSymbol();
  126. static Boolean        isSameString(), isWhiteSpace();
  127. unsigned long        hashString();
  128. static void        declareName(), undeclareName(), parseVariableName();
  129. static OOP        scanName(), internCountedString();
  130. static int        instanceVariableIndex(), localVarIndex();
  131.  
  132. typedef struct SymbolListStruct *SymbolList;
  133.  
  134. struct SymbolListStruct {
  135.   OOP        symbol;
  136.   int        index;
  137.   SymbolList    prevSymbol;
  138. };
  139.   
  140. static SymbolList    symbolList;
  141. static int        methodArguments, frameIndex, maxFrameIndex;
  142.  
  143.  
  144. int getArgCount()
  145. {
  146.   return (methodArguments);
  147. }
  148.  
  149. int getTempCount()
  150. {
  151.   return (maxFrameIndex - methodArguments);
  152. }
  153.  
  154. void initArgCount()
  155. {
  156.   methodArguments = 0;
  157. }
  158.  
  159. void initTempCount()
  160. {
  161. }
  162.  
  163. void declareArguments(args)
  164. TreeNode args;
  165. {
  166.   symbolList = nil;
  167.   frameIndex = 0;
  168.   maxFrameIndex = 0;
  169.  
  170.   if (args->nodeType == unaryExprType) {
  171.     return;
  172.   } else if (args->nodeType == binaryExprType) {
  173.     declareName(args->vExpr.expression->vList.name);
  174.     methodArguments++;
  175.   } else {
  176.     for(args = args->vExpr.expression; args != nil; args = args->vList.next) {
  177.       declareName(args->vList.value->vList.name);
  178.       methodArguments++;
  179.     }
  180.   }
  181. }
  182.   
  183. void declareTemporaries(temps)
  184. TreeNode temps;
  185. {
  186.   for( ; temps != nil; temps = temps->vList.next) {
  187.     declareName(temps->vList.name);
  188.   }
  189. }
  190.  
  191. void declareBlockArguments(args)
  192. TreeNode args;
  193. {
  194.   for( ; args != nil; args = args->vList.next) {
  195.     declareName(args->vList.name);
  196.   }
  197. }
  198.  
  199. static void declareName(name)
  200. char    *name;
  201. {
  202.   SymbolList    newList;
  203.  
  204.   newList = (SymbolList)malloc(sizeof(struct SymbolListStruct));
  205.   newList->symbol = internString(name);
  206.   newList->index = frameIndex++;
  207.   maxFrameIndex = max(maxFrameIndex, frameIndex);
  208.   newList->prevSymbol = symbolList;
  209.   symbolList = newList;
  210. }
  211.  
  212. void undeclareArguments(args)
  213. TreeNode args;
  214. {
  215.   if (args == nil) {
  216.     return;
  217.   }
  218.  
  219.   if (args->nodeType == unaryExprType) {
  220.     return;
  221.   } else if (args->nodeType == binaryExprType) {
  222.     undeclareName(true);
  223.   } else {
  224.     for(args = args->vExpr.expression; args != nil; args = args->vList.next) {
  225.       undeclareName(true);
  226.     }
  227.   }
  228. }
  229.  
  230. void undeclareTemporaries(temps)
  231. TreeNode temps;
  232. {
  233.   for( ; temps != nil; temps = temps->vList.next) {
  234.     undeclareName(true);
  235.   }
  236. }
  237.  
  238. void undeclareBlockArguments(args)
  239. TreeNode args;
  240. {
  241.   if (args == nil) {
  242.     return;
  243.   }
  244.  
  245.   for( ; args != nil; args = args->vList.next) {
  246.     undeclareName(false);
  247.   }
  248. }
  249.  
  250. static void undeclareName(decrFrameIndex)
  251. Boolean decrFrameIndex;
  252. {
  253.   SymbolList    oldList;
  254.  
  255.   oldList = symbolList;
  256.   symbolList = symbolList->prevSymbol;
  257.   free(oldList);
  258.   if (decrFrameIndex) {
  259.     frameIndex--;
  260.   }
  261. }
  262.  
  263. OOP findClassVariable(varName)
  264. OOP    varName;
  265. {
  266.   OOP        classOOP, assocOOP, classVariableOOP;
  267.  
  268.   if (oopClass(thisClass) == behaviorClass
  269.       || oopClass(thisClass) == classDescriptionClass) {
  270.     /* classDescriptions and above don't have class or pool variables */
  271.     /* ### this isn't quite the right test; we probably should be testing
  272.        for if we have a classClass or some derivative of that */
  273.     return (nilOOP);
  274.   }
  275.  
  276.   for (classOOP = thisClass; !isNil(classOOP);
  277.        classOOP = superClass(classOOP)) {
  278.     if (oopClass(classOOP) == metaclassClass) {
  279.       /* pretend that metaclasses have the class variables and shared
  280.      pools that their instance classes do */
  281.       classVariableOOP = metaclassInstance(classOOP);
  282.     } else {
  283.       classVariableOOP = classOOP;
  284.     }
  285.     assocOOP =
  286.       dictionaryAssociationAt(classVariableDictionary(classVariableOOP),
  287.                   varName);
  288.     if (!isNil(assocOOP)) {
  289.       return (assocOOP);
  290.     }
  291.  
  292.     assocOOP = findSharedPoolVariable(classVariableOOP, varName);
  293.     if (!isNil(assocOOP)) {
  294.       return (assocOOP);
  295.     }
  296.   }
  297.  
  298.   return (nilOOP);
  299. }
  300.  
  301.  
  302. SymbolEntry findVariable(varName)
  303. char    *varName;
  304. {
  305.   OOP        varAssoc, symbol;
  306.   int        index;
  307.  
  308.   symbol = internString(varName);
  309.   index = localVarIndex(symbol);
  310.   if (index >= 0) {
  311.     return (allocSymbolEntry(temporaryScope, symbol, index));
  312.   }
  313.  
  314.   index = instanceVariableIndex(symbol);
  315.   if (index >= 0) {
  316.     return (allocSymbolEntry(receiverScope, symbol, index));
  317.   }
  318.  
  319.   varAssoc = findClassVariable(symbol);
  320.   if (isNil(varAssoc)) {
  321.     return (nil);
  322.   }
  323.  
  324.   index = addForcedObject(varAssoc);
  325.  
  326.   return (allocSymbolEntry(globalScope, varAssoc, index));
  327. }
  328.  
  329. static int instanceVariableIndex(symbol)
  330. OOP    symbol;
  331. {
  332.   OOP        arrayOOP;
  333.   int        index, numVars;
  334.  
  335.  
  336.   if (oopClass(thisClass) == behaviorClass) {
  337.     /* behaviors have no instance variables */
  338.     return (-1);
  339.   }
  340.  
  341.   arrayOOP = instanceVariableArray(thisClass);
  342.   numVars = numOOPs(oopToObj(arrayOOP));
  343.  
  344.   for (index = 1; index <= numVars; index++) {
  345.     if (arrayAt(arrayOOP, index) == symbol) {
  346.       return (index-1);
  347.     }
  348.   }
  349.  
  350.   return (-1);
  351. }
  352.  
  353. static int localVarIndex(symbol)
  354. OOP    symbol;
  355. {
  356.   SymbolList    s;
  357.  
  358.   for (s = symbolList; s != nil && symbol != s->symbol; s = s->prevSymbol);
  359.  
  360.   if (s != nil) {        /* found one */
  361.     return (s->index);
  362.   } else {
  363.     return (-1);
  364.   }
  365. }
  366.  
  367. static SymbolEntry allocSymbolEntry(scope, symbol, index)
  368. ScopeType    scope;
  369. OOP        symbol;
  370. int        index;
  371. {
  372.   SymbolEntry    ent;
  373.  
  374.   ent = (SymbolEntry)malloc(sizeof(struct SymbolEntryStruct));
  375.   ent->scope = scope;
  376.   ent->symbol = symbol;
  377.   ent->varIndex = index;
  378.   return (ent);
  379. }
  380.  
  381.  
  382. void freeSymbolEntry(ent)
  383. SymbolEntry ent;
  384. {
  385.   free(ent);
  386. }
  387.  
  388.  
  389. OOP makeInstanceVariableArray(superclassOOP, variableString)
  390. OOP    superclassOOP;
  391. Byte    *variableString;
  392. {
  393.   OOP        arrayOOP, superArrayOOP, name;
  394.   int        index, numInstanceVars, superInstanceVars;
  395.   Byte        *p;
  396.  
  397.   if (variableString == nil) {
  398.     variableString = (Byte *)"";
  399.   }
  400.  
  401.  
  402.   if (isNil(superclassOOP)) {
  403.     superArrayOOP = nilOOP;
  404.     superInstanceVars = numInstanceVars = 0;
  405.   } else {
  406.     superArrayOOP = instanceVariableArray(superclassOOP);
  407.     superInstanceVars = numInstanceVars = numOOPs(oopToObj(superArrayOOP));
  408.   }
  409.  
  410.   for (p = variableString; *p; ) {
  411.     /* skip intervening whitespace */
  412.     name = scanName(&p);
  413.     if (!isNil(name)) {
  414.       numInstanceVars++;
  415.     }
  416.   }
  417.  
  418.   if (numInstanceVars == 0) {
  419.     return (nilOOP);        /* no instances here */
  420.   }
  421.  
  422.   arrayOOP = arrayNew(numInstanceVars);
  423.  
  424.   /* inherit variables from parent */
  425.   for (index = 1; index <= superInstanceVars; index++) {
  426.     arrayAtPut(arrayOOP, index, arrayAt(superArrayOOP, index));
  427.   }
  428.  
  429.   /* now add our own variables */
  430.   for (p = variableString; *p; index++) {
  431.     /* skip intervening whitespace */
  432.     name = scanName(&p);
  433.     if (!isNil(name)) {
  434.       arrayAtPut(arrayOOP, index, name);
  435.     }
  436.   }
  437.  
  438.   return (arrayOOP);
  439. }
  440.  
  441. OOP makeClassVariableDictionary(classOOP, variableNames)
  442. OOP    classOOP;
  443. Byte    *variableNames;
  444. {
  445.   OOP        dictionaryOOP, name;
  446.   Byte        *p;
  447.  
  448.   if (variableNames == nil) {
  449.     variableNames = (Byte *)"";
  450.   }
  451.  
  452.   dictionaryOOP = dictionaryNew();
  453.  
  454.   for (p = variableNames; *p; ) {
  455.     name = scanName(&p);
  456.     if (!isNil(name)) {
  457.       /* ### error if already exists */
  458.       dictionaryAtPut(dictionaryOOP, name, nilOOP);
  459.     }
  460.   }
  461.  
  462.   if (dictionarySize(dictionaryOOP) == 0) {
  463.     dictionaryOOP = nilOOP;
  464.   }
  465.  
  466.   return (dictionaryOOP);
  467. }
  468.  
  469. OOP makePoolArray(classOOP, poolNames)
  470. OOP    classOOP;
  471. Byte     *poolNames;
  472. {
  473.   OOP        pools, name;
  474.   int        numPools, i;
  475.   Byte        *p, *e;
  476.  
  477.   if (poolNames == nil) {
  478.     poolNames = (Byte *)"";
  479.   }
  480.   
  481.   /* count the number of new pool names */
  482.   for (p = poolNames, numPools = 0; *p; ) {
  483.     parseVariableName(&p, &e);
  484.     if (p != e) {
  485.       numPools++;
  486.       p = e;
  487.     }
  488.   }
  489.  
  490.   pools = arrayNew(numPools);
  491.  
  492.   for (p = poolNames, i = 1; *p; i++) {
  493.     name = scanName(&p);
  494.     if (!isNil(name)) {
  495.       /* ### error if already exists in parent?,
  496.      or if value isn't a dictionary */
  497.       /* ### should I keep these as names?  or associations?  Should
  498.      I look up the names somewhere other than in the smalltalk
  499.      dictionary?  Need to check for undefineds? */
  500.       arrayAtPut(pools, i, dictionaryAt(smalltalkDictionary, name));
  501.     }
  502.   }
  503.  
  504.   if (numPools == 0) {        /* ### maybe change this to leave empty array */
  505.     pools = nilOOP;
  506.   }
  507.  
  508.   return (pools);
  509. }
  510.  
  511. /*
  512.  *    static OOP scanName(pp)
  513.  *
  514.  * Description
  515.  *
  516.  *    Scan a variable name (letters and digits, initial letter), and return a
  517.  *    symbol for it.
  518.  *
  519.  * Inputs
  520.  *
  521.  *    pp    : pointer to a pointer to the start of the string to be scanned.
  522.  *        May be pointing at either whitespace or start of variable.  At
  523.  *        end, points to first character after the parsed variable name,
  524.  *        which may be NUL. 
  525.  *
  526.  * Outputs
  527.  *
  528.  *    Symbol for variable name, or nilOOP if none found.  pp points to first
  529.  *    char after symbol name (if any).
  530.  */
  531. static OOP scanName(pp)
  532. Byte    **pp;
  533. {
  534.   Byte        *end, *str;
  535.   long        len;
  536.  
  537.   parseVariableName(pp, &end);
  538.   len = end - *pp;
  539.   if (len == 0) {
  540.     return (nilOOP);
  541.   }
  542.  
  543.  
  544.   str = (Byte *)alloca(len + 1);
  545.   strncpy(str, *pp, len);
  546.   str[len] = '\0';
  547.  
  548.   *pp = end;
  549.  
  550.   return (internString(str));
  551. }
  552.  
  553. static void parseVariableName(pp, endp)
  554. Byte    **pp, **endp;
  555. {
  556.   register Byte    *p, *e;
  557.  
  558.   p = *pp;
  559.   e = *endp;
  560.  
  561.   while (isWhiteSpace(*p)) {
  562.     p++;
  563.   }
  564.  
  565.   /* ### check for non-null here and not alnum; we've jammed on a bogus char
  566.      and it's an error */
  567.  
  568.   /* variable name extends from p to e-1 */
  569.   for (e = p; *e; e++) {
  570.     if (!isalnum(*e)) {
  571.       break;
  572.     }
  573.   }
  574.  
  575.   *pp = p;
  576.   *endp = e;
  577. }
  578.  
  579. static Boolean isWhiteSpace(c)
  580. Byte    c;
  581. {
  582.    return (c == ' ' || c == '\t' || c == '\n' || c == '\f');
  583. }
  584.  
  585. OOP internStringOOP(stringOOP)
  586. OOP    stringOOP;
  587. {
  588.   int        len;
  589.  
  590.   len = stringOOPLen(stringOOP);
  591.   return (internCountedString(stringOOPChars(stringOOP), len));
  592. }
  593.  
  594. OOP internString(str)
  595. char    *str;
  596. {
  597.   int        len;
  598.  
  599.   len = strlen(str);
  600.   return (internCountedString(str, len));
  601. }
  602.  
  603. static OOP internCountedString(str, len)
  604. Byte    *str;
  605. int    len;
  606. {
  607.   unsigned long    index;
  608.   SymLink    link;
  609.   Symbol    symbol;
  610.   OOP        symbolOOP, linkOOP;
  611.  
  612.   index = (hashString(str, len) % numOOPs(oopToObj(symbolTable))) + 1;
  613.   for (linkOOP = arrayAt(symbolTable, index); !isNil(linkOOP);
  614.        linkOOP = link->nextLink) {
  615.     link = (SymLink)oopToObj(linkOOP);
  616.     if (isSameString(str, link->symbol, len)) {
  617.       return (link->symbol);
  618.     }
  619.   }
  620.  
  621.   /* no match, have to add it to head of list */
  622.   
  623.   symbol = (Symbol)newInstanceWith(symbolClass, (long)len);
  624.   strncpy(symbol->symString, str, len);
  625.   symbolOOP = allocOOP(symbol);
  626.   symbolOOP->flags |= (4 - len) & 3;
  627.  
  628.   link = (SymLink)newInstance(symLinkClass);
  629.   link->nextLink = arrayAt(symbolTable, index);
  630.   maybeMoveOOP(link->nextLink);    /* make sure it's here with us */
  631.   link->symbol = symbolOOP;
  632.   arrayAtPut(symbolTable, index, allocOOP(link));
  633.   return (symbolOOP);
  634. }
  635.  
  636.  
  637. static Symbol makeNewSymbol(str, len)
  638. Byte    *str;
  639. int    len;
  640. {
  641.   Symbol    symbol;
  642.  
  643.   symbol = (Symbol)newInstanceWith(symbolClass, (long)len);
  644.   strncpy(symbol->symString, str, len);
  645.  
  646.   return (symbol);
  647. }
  648.  
  649. #ifdef preserved_code /* Sun Oct  8 10:30:55 1989 */
  650. /**/static Boolean isSymbol(oop)
  651. /**/OOP    oop;
  652. /**/{
  653. /**/  if (isNil(oop)) {
  654. /**/    return (false);
  655. /**/  }
  656. /**/
  657. /**/  /* ??? are there subclasses of symbol ... do we need to worry about it? */
  658. /**/  return (oop->object->objClass == symbolClass);
  659. /**/}
  660. #endif /* preserved_code Sun Oct  8 10:30:55 1989 */
  661.  
  662. static Boolean isSameString(str, oop, len)
  663. char    *str;
  664. OOP    oop;
  665. int    len;
  666. {
  667.   if (stringOOPLen(oop) == len) {
  668.     return (strncmp(str, ((Symbol)oopToObj(oop))->symString, len) == 0);
  669.   }
  670.  
  671.   return (false);
  672. }
  673.  
  674. int stringOOPLen(oop)
  675. OOP    oop;
  676. {
  677.   return (oopSizeBytes(oop) - (oop->flags & EMPTY_BYTES));
  678. }
  679.  
  680.  
  681. unsigned long hashString(str, len)
  682. char    *str;
  683. int    len;
  684. {
  685. #ifdef dragon_book
  686. /* from Dragon Book, p436 */
  687.   unsigned long hashVal = 0, carry;
  688.  
  689.   for ( ; len > 0; str++, len--) {
  690.     hashVal = (hashVal << 4) + (*str);
  691.     if (carry = (hashVal & 0xf0000000)) {
  692.       hashVal ^= (carry >> 24);
  693.       hashVal ^= carry;
  694.     }
  695.   }
  696.  
  697.   return (hashVal);
  698. #else
  699.   long    result = 0L;
  700.  
  701.   for (; len > 0; str++, len--) {
  702.     result = (result << 1) /* | (result < 0) */;
  703.     result ^= *str;
  704.   }
  705.  
  706.   return ((unsigned long)result);
  707. #endif /* ! dragon_book */
  708. }
  709.  
  710. void printSymbol(symbol)
  711. OOP    symbol;
  712. {
  713.   if (isNil(symbol)) {
  714.     printf(nilName);
  715.   } else {
  716.     printString(symbol);
  717.   }
  718. }
  719.  
  720. void printString(string)
  721. OOP    string;
  722. {
  723.   int        len;
  724.  
  725.   len = stringOOPLen(string);
  726.   fwrite(oopToObj(string)->data, sizeof(Byte), len, stdout);
  727.   fflush(stdout);
  728. }
  729.  
  730. /*
  731.  *    char *symbolAsString(symbolOOP)
  732.  *
  733.  * Description
  734.  *
  735.  *    Given a symbol, this routine returns a C string that corresponds to the
  736.  *    name of the symbol.  The returned value is a pointer to a static area,
  737.  *    so if it's to be used for anything other than immediate output, the
  738.  *    caller needs to make a copy of the retured string.
  739.  *
  740.  * Inputs
  741.  *
  742.  *    symbolOOP: 
  743.  *        An OOP for a symbol
  744.  *
  745.  * Outputs
  746.  *
  747.  *    Pointer to a C string that contains the symbol name.
  748.  */
  749. char *symbolAsString(symbolOOP)
  750. OOP    symbolOOP;
  751. {
  752.   static char    stringBuf[256];    /* probably large enough for most symbols */
  753.   int        len;
  754.   Symbol    symbol;
  755.  
  756.   symbol = (Symbol)oopToObj(symbolOOP);
  757.  
  758.   len = stringOOPLen(symbolOOP);
  759.   if (len >= sizeof(stringBuf)) {
  760.     errorf("symbol name too long: %d, max is %d", len, sizeof(stringBuf));
  761.   }
  762.   strncpy(stringBuf, symbol->symString, len);
  763.   stringBuf[len] = '\0';
  764.   return (stringBuf);
  765. }
  766.  
  767. /*
  768.  *    void printSymbols()
  769.  *
  770.  * Description
  771.  *
  772.  *    This routine is used for symbol table debugging only.
  773.  *
  774.  */
  775. void printSymbolChain();    /* ### hack */
  776. void printSymbols()
  777. {
  778.   unsigned long    i;
  779.   
  780.   for (i = 1; i <= numOOPs(oopToObj(symbolTable)); i++) {
  781.     printf("Table[%d]:\n", i);
  782.     printSymbolChain(i);
  783.     printf("\n");
  784.   }
  785. }
  786.  
  787. void printSymbolChain(i)
  788. unsigned long i;
  789. {
  790.   SymLink    link;
  791.   OOP        linkOOP;
  792.   for (linkOOP = arrayAt(symbolTable, i); !isNil(linkOOP);
  793.        linkOOP = link->nextLink) {
  794.     link = (SymLink)oopToObj(linkOOP);
  795.     printf("%d:", linkOOP - oopTable); /* ### */
  796.     printSymbol(link->symbol);
  797.     printf("->");
  798.   }
  799. }
  800.  
  801.  
  802. void printSymLink(symLinkOOP)
  803. OOP    symLinkOOP;
  804. {
  805.   SymLink    link;
  806.  
  807.   link = (SymLink)oopToObj(symLinkOOP);
  808.  
  809.   printObject(link->symbol);
  810. }
  811.  
  812. void initSymbols()
  813. {
  814.   andColonSymbol             = internString("and:");
  815.   andSymbol            = internString("&");
  816.   atColonPutColonSymbol         = internString("at:put:");
  817.   atColonSymbol             = internString("at:");
  818.   atEndSymbol                 = internString("atEnd");
  819.   bitAndColonSymbol             = internString("bitAnd:");
  820.   bitOrColonSymbol             = internString("bitOr:");
  821.   bitShiftColonSymbol             = internString("bitShift:");
  822.   blockCopyColonSymbol             = internString("blockCopy:");
  823.   byteArraySymbol        = internString("byteArray");
  824.   byteArrayOutSymbol        = internString("byteArrayOut");
  825.   charSymbol                    = internString("char");
  826.   classSymbol                 = internString("class");
  827.   cObjectSymbol                 = internString("cObject");
  828.   divideSymbol                 = internString("/");
  829.   doColonSymbol             = internString("do:");
  830.   doesNotUnderstandColonSymbol  = internString("doesNotUnderstand:");
  831.   doubleSymbol                  = internString("double");
  832.   equalSymbol                 = internString("=");
  833.   falseSymbol            = internString("false");
  834.   greaterEqualSymbol             = internString(">=");
  835.   greaterThanSymbol             = internString(">");
  836.   ifFalseColonIfTrueColonSymbol = internString("ifFalse:ifTrue:");
  837.   ifFalseColonSymbol             = internString("ifFalse:");
  838.   ifTrueColonIfFalseColonSymbol = internString("ifTrue:ifFalse:");
  839.   ifTrueColonSymbol             = internString("ifTrue:");
  840.   integerDivideSymbol             = internString("//");
  841.   intSymbol                     = internString("int");
  842.   lessEqualSymbol             = internString("<=");
  843.   lessThanSymbol             = internString("<");
  844.   longSymbol                    = internString("long");
  845.   minusSymbol                 = internString("-");
  846.   newColonSymbol             = internString("new:");
  847.   newSymbol                 = internString("new");
  848.   nextPutColonSymbol             = internString("nextPut:");
  849.   nextSymbol                 = internString("next");
  850.   nilSymbol            = internString("nil");
  851.   notEqualSymbol             = internString("~=");
  852.   notSameObjectSymbol        = internString("~~");
  853.   orColonSymbol             = internString("or:");
  854.   orSymbol            = internString("|");
  855.   plusSymbol                 = internString("+");
  856.   remainderSymbol             = internString("\\");
  857.   sameObjectSymbol             = internString("==");
  858.   selfSymbol            = internString("self");
  859.   sizeSymbol                 = internString("size");
  860.   smalltalkSymbol        = internString("smalltalk");
  861.   stringOutSymbol               = internString("stringOut");
  862.   stringSymbol                  = internString("string");
  863.   superSymbol            = internString("super");
  864.   symbolSymbol                  = internString("symbol");
  865.   thisContextSymbol        = internString("thisContext");
  866.   timesSymbol                 = internString("*");
  867.   trueSymbol            = internString("true");
  868.   unknownSymbol                 = internString("unknown");
  869.   valueColonSymbol             = internString("value:");
  870.   valueColonValueColonSymbol    = internString("value:value:");
  871.   valueColonValueColonValueColonSymbol = internString("value:value:value:");
  872.   valueSymbol                 = internString("value");
  873.   valueWithArgumentsColonSymbol = internString("valueWithArguments:");
  874.   variadicSymbol                = internString("variadic");
  875.   voidSymbol                    = internString("void");
  876.   whileFalseColonSymbol            = internString("whileFalse:");
  877.   whileTrueColonSymbol             = internString("whileTrue:");
  878. }
  879.